#!/usr/bin/perl -w   ; useful for syntax checking
package clreqd_modules;

use strict;
use cldb;
use Config;
use mnttab;
use fstypes;

sub mount_app_fs {
my %ARGS=@_;

	local $SIG{CHLD}='DEFAULT';
	my $FS=undef; my $LV=undef; my $VG=undef;
	$FS=$ARGS{FS} if(exists($ARGS{FS}) && defined($ARGS{FS}));
	$VG=$ARGS{VG} if(exists($ARGS{VG}) && defined($ARGS{VG}));
	$LV=$ARGS{LV} if(exists($ARGS{LV}) && defined($ARGS{LV}));
	my $APP=$ARGS{APPLICATION};
	my $CLDB=new cldb("$::ENV{TRUECL_CFG}/config.db");
	if(!defined($CLDB)) {
		return "ERROR - Unable to config to 'config' database.";
	}
	my $res=$CLDB->get_rows("SELECT * FROM application_fs WHERE name = '$APP';");
	my $res2=$CLDB->get_rows("SELECT * FROM applications WHERE name = '$APP';");
	if(!defined($res2->[0]->{nodes})) {
		return "ERROR - Application '$APP' is unknown.";
	}

	my $s=$res2->[0]->{storage};
	#################################################################
	# Now open open the configuration database to get the storage	#
	# spec and list of volume groups...				#
	#################################################################

	if(! -f "$::ENV{TRUECL_CODE}/lib/storage_spec/$s.pm") {
		return "ERROR - Storage spec '$s' not available.";
	}
	$CLDB->disconnect;

	if(!defined($res->[0]->{mountpnt})) {
		::msg("No mount points configured for '$APP;");
		return "OK 0 0";
	}

	#################################################################
	# Generate a storage spec of the type necessary.		#
	#################################################################

	eval "use storage_spec::$s;";
	my $STORAGE=eval "new storage_spec::$s;";
	if(!defined($STORAGE)) {
		return "ERROR - Unable to use storage spec - storage_spec::$s";
	}

	my $crec; my $cnt=0; my $failed=0;
	my $mnttab=new mnttab;
	for $crec (@$res) {
		if(defined($VG) && defined($LV)) {
			if(! ($VG eq $crec->{vg} && $LV eq $crec->{lv})) {
				next;
			}
		} elsif(defined($FS) && defined($crec->{mountpnt}) && $crec->{mountpnt} ne $FS) {
			next;
		}
		#########################################################
		# If the fstype eq NONE then we don't actually do 	#
		# anything since this is a raw logical volume entry.	#
		#########################################################
		if($crec->{fstype} eq "NONE") {
			next;
		}
		my $cmd;
		if($mnttab->is_mounted($crec->{mountpnt})) {
			::msg("Not mounting '$crec->{mountpnt}' - already mounted.");
			next;
		}
		if(-x "/bin/mount") {
			$cmd="/bin/mount ";
		 } elsif(-x "/sbin/mount") {
			$cmd="/sbin/mount ";
		} else {
			$cmd="/usr/sbin/mount ";
		}
		if($Config{'osname'} eq "linux" || $Config{'osname'} eq "freebsd") {
			$cmd.="-t $crec->{fstype} ";
		} else {
			$cmd.="-F $crec->{fstype} ";
		}
		#########################################################
		# Some 'options' are not actually options and should	#
		# be removed from the list before attempting to build	#
		# the mount command.					#
		#########################################################
		{
			my @new=();
			my @F=split(/,/,$crec->{options});
			my @bad=('^NFSv3$','^NFSv2$','^dev=\d+$');
			for my $copt (@F) {
				my $bad_opt=0;
				for my $cbad (@bad) {
					if($copt =~ /$cbad/) {
						$bad_opt=1;
						last;
					}
				}
				next if $bad_opt;
				push @new,$copt;
			}
			$crec->{options}=join(",",@new);
		}

		if(length($crec->{options})) {
			$cmd.="-o $crec->{options} ";
		}
		my $vgname=$crec->{vg};
		my $lvname=$crec->{lv};
		my $fstype=$crec->{fstype};
		#########################################################
		# If LVM is in use then the device to use will be	#
		# /dev/VGNAME/LVNAME. If VxVM will be 			#
		# /dev/vx/dsk/VGNAME/LVNAME.				#
		#########################################################
		my ($_r1,$block_dev,$fsck_dev)=$STORAGE->local_devname($vgname,$lvname,$APP);

		if($_r1 == 0) {
			::warning("Got error from local_devname:\n$block_dev");
			$failed++;
			next;
		}

		#########################################################
		# If this is NFS: then we ignore some local checks...	#
		# but take off prefix for mounting.			#
		#########################################################

		if($block_dev =~ /^[A-Z]+:/) {
			$block_dev =~ s/^[A-Z]+://;
		} else {
			if(! -e $block_dev) {
				::warning("Device for $vgname/$lvname [$block_dev] not found - ignoring.");
				$failed++;
				next;
			}
			if(length($fsck_dev) && ! -e $fsck_dev) {
				::warning("Fsck Device for $vgname/$lvname [$fsck_dev] not found - ignoring.");
				$failed++;
				next;
			}
		}
		
		#########################################################
		# Only fsck if a device has been provided.		#
		#########################################################

		if(length($fsck_dev)) {
			my ($fs_res,$fs_err)=do_fsck($fstype,$fsck_dev);
			if($fs_res==0) {
				::warning("Fsck for $vgname/$lvname [$fsck_dev] failed! - ignoring.Error:\n$fs_err");
				$failed++;
				next;
			}
		}

		$cmd.="$block_dev ";
		if(! -d $crec->{mountpnt}) {
			::warning("Mount point '$crec->{mountpnt}' does not exist - ignoring.");
			$failed++;
			next;
		}
		$cmd.=$crec->{mountpnt};
		my $rr=`$cmd 2>&1`; chomp $rr;
		if(length($rr)) {
			::error("Unable to mount '$crec->{mountpnt}':",$rr,"Command was:",$cmd);
			$failed++;
			return "FAIL $cnt $failed";
		}
		$cnt++;
	}
	return "OK $cnt $failed";
}

1;
